package com.example.jspweb.service;

import com.example.jspweb.model.LocationDto;
import com.example.jspweb.model.VrpRequest;
import com.example.jspweb.model.VrpResponse;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.util.Solutions;
import org.springframework.stereotype.Service;
import java.util.*;

/**
 * VRP服务类 - 车辆路径规划服务
 */
@Service
public class VrpService {
    // 容量维度索引
    private static final int WEIGHT_INDEX = 0;

    /**
     * 求解VRP问题
     * 
     * @param request VRP请求
     * @return VRP响应
     */
    public VrpResponse solve(VrpRequest request) {
        try {
            // 创建车辆类型
            VehicleTypeImpl vehicleType = VehicleTypeImpl.Builder.newInstance("vehicleType")
                .addCapacityDimension(WEIGHT_INDEX, request.getVehicle().getCapacity())
                .setCostPerDistance(1.0)
                .build();

            // 创建车辆和仓库位置
            LocationDto depotLocationDto = request.getVehicle().getStartLocation();
            Location depotLocation = Location.newInstance(depotLocationDto.getX(), depotLocationDto.getY());

            VehicleImpl vehicle = VehicleImpl.Builder.newInstance(request.getVehicle().getId())
                .setStartLocation(depotLocation)
                .setEndLocation(depotLocation)
                .setType(vehicleType)
                .build();

            // 创建VRP问题构建器
            VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
            vrpBuilder.addVehicle(vehicle);
            vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
            
            // 添加服务点
            Map<String, VrpRequest.Service> serviceMap = new HashMap<>();
            for (VrpRequest.Service requestService : request.getServices()) {
                LocationDto serviceLocationDto = requestService.getLocation();
                Location serviceLocation = Location.newInstance(
                    serviceLocationDto.getX(),
                    serviceLocationDto.getY()
                );

                com.graphhopper.jsprit.core.problem.job.Service service = 
                    com.graphhopper.jsprit.core.problem.job.Service.Builder
                        .newInstance(requestService.getId())
                        .addSizeDimension(WEIGHT_INDEX, requestService.getDemand())
                        .setLocation(serviceLocation)
                        .setServiceTime(requestService.getServiceTime())
                        .build();

                vrpBuilder.addJob(service);
                serviceMap.put(requestService.getId(), requestService);
            }

            // 构建和求解问题
            VehicleRoutingProblem problem = vrpBuilder.build();
            VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(problem)
                .setProperty(Jsprit.Parameter.ITERATIONS, "2000")
                .buildAlgorithm();

            Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
            VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions);

            if (bestSolution == null) {
                throw new RuntimeException("未找到可行解");
            }

            // 构建响应
            VrpResponse response = new VrpResponse();
            response.setStatus("success");
            response.setCost(bestSolution.getCost());
            
            List<VrpResponse.Route> routes = new ArrayList<>();
            
            // 处理路线
            for (VehicleRoute route : bestSolution.getRoutes()) {
                List<VrpResponse.Route.Stop> stops = new ArrayList<>();
                LocationDto prevLocationDto = depotLocationDto;
                double totalDistance = 0;
                double totalTime = 0;
                int totalDemand = 0;

                // 处理每个停靠点
                for (TourActivity act : route.getActivities()) {
                    if (act instanceof TourActivity.JobActivity) {
                        TourActivity.JobActivity jobAct = (TourActivity.JobActivity) act;
                        Location currentLocation = jobAct.getLocation();
                        LocationDto currentLocationDto = new LocationDto(
                            currentLocation.getCoordinate().getX(),
                            currentLocation.getCoordinate().getY()
                        );
                        
                        // 使用LocationDto的distanceTo方法计算距离
                        double legDistance = prevLocationDto.distanceTo(currentLocationDto);
                        totalDistance += legDistance;
                        
                        String serviceId = jobAct.getJob().getId();
                        VrpRequest.Service requestService = serviceMap.get(serviceId);

                        if (requestService != null) {
                            VrpResponse.Route.Stop stop = new VrpResponse.Route.Stop();
                            stop.setServiceId(serviceId);
                            stop.setLocation(currentLocationDto);
                            stop.setDemand(requestService.getDemand());
                            stop.setArrivalTime(jobAct.getArrTime());
                            stop.setDepartureTime(jobAct.getEndTime());

                            stops.add(stop);
                            totalTime = jobAct.getEndTime();
                            totalDemand += requestService.getDemand();
                            prevLocationDto = currentLocationDto;
                        }
                    }
                }

                // 添加返回仓库的距离和时间
                totalDistance += prevLocationDto.distanceTo(depotLocationDto);
                totalTime += prevLocationDto.distanceTo(depotLocationDto);

                VrpResponse.Route responseRoute = new VrpResponse.Route();
                responseRoute.setVehicleId(route.getVehicle().getId());
                responseRoute.setStops(stops);
                responseRoute.setTotalDistance(totalDistance);
                responseRoute.setTotalTime(totalTime);
                responseRoute.setTotalDemand(totalDemand);

                routes.add(responseRoute);
            }

            response.setRoutes(routes);
            return response;

        } catch (Exception e) {
            VrpResponse errorResponse = new VrpResponse();
            errorResponse.setStatus("error");
            errorResponse.setMessage("路径规划失败: " + e.getMessage());
            return errorResponse;
        }
    }
}
